package com.ld.security.auth.common.base.aop;

import com.ld.security.common.core.anno.SemaphoreMapping;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Semaphore;

@Component
@Aspect
@Order(0)
public class SemaphoreMappingAop {

    private Map<Integer,Semaphore> map = new HashMap<>();

    @Pointcut("@annotation(com.ld.security.common.core.anno.SemaphoreMapping)")
    public void aop() {

    }


    private Semaphore getSemaphore(Method method){
        SemaphoreMapping semaphoreMapping =  AnnotationUtils.findAnnotation(method, SemaphoreMapping.class);
        Integer id = method.hashCode();
        Semaphore semaphore =  map.get(id);
        if(semaphore == null){
            semaphore = new Semaphore(semaphoreMapping.value());
            map.put(id,semaphore);
        }
        return semaphore;
    }

   @Around("aop()")
    public Object doAroundAdvice(ProceedingJoinPoint pjp) throws Throwable{
        MethodSignature ms = (MethodSignature) pjp.getSignature();
        Method method = ms.getMethod();
        Semaphore semaphore = getSemaphore(method);
        semaphore.acquire();
        Object val =  pjp.proceed();
        semaphore.release();
        return val;
    }



}
